package com.rds.common.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.Proxy;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;


/**
 * Http 請求服務工具类 Copyright(c) 2019 China National Petroleum Corporation.
 * http://www.sunnyoptical.cn/
 * 
 * @version 1.0
 * @author Ge WeiJian
 * @since 2019年4月11日
 */
@Component
public class POHttpUtil {

	private static final Logger LOG = LoggerFactory.getLogger(POHttpUtil.class);

	private static final String ENCODE_CODE = "UTF-8";
	
	
	private static String upperCase(String str) {
        return str == null ? null : str.toUpperCase();
    }
	
	
	/**
	 * 使用Post方式 -- 需要传递Map参数 -- 需要传递 http请求的URL地址 -- 可传递Proxy代理服务 （不需要代理传递NULL）
	 * -- 可传递代理服务器的端口 （不需要代理传递NULL）
	 * 
	 * POST请求方式 需要设置 RequestProperty 编码 长度 POST请求有 body
	 * 
	 * @param requestUrl
	 *            请求URL
	 * @param params
	 *            请求数据
	 * @param userName
	 *            用户
	 * @param passWord
	 *            密码
	 * @param proxy
	 *            代理服务
	 * @param port
	 *            代理服务端口
	 * @return Map<String,Object> key:status value: S or R key:msg
	 * @version 1.0
	 * @since 2015-12-11
	 */
	public static String doPostRequest(String requestUrl, 
											 String params, 
											 String userName,
											 String passWord,
											 String proxy, 
											 Integer port) {

		StringBuffer respStr = new StringBuffer();
		Map<String, Object> respMap = new HashMap<String, Object>();
		String respStatus = "S";

		InputStream in = null;
		BufferedReader bReader = null;
		OutputStream os = null;
		HttpURLConnection conn = null;

		try {

			/** - 实例化URL对象 */
			URL url = new URL(requestUrl);
			/** - 打开 HttpURLConnection 链接 */
			conn = openConn(url, proxy, port);

			byte[] data = params.getBytes(ENCODE_CODE);

			conn.setConnectTimeout(50 * 1000);  /*-? 设置超时时间  1000毫秒 */
			conn.setReadTimeout(300*1000);
			conn.setRequestMethod("POST"); 		/*-? 设置请求方式 */
			conn.setDoOutput(true); 			/*-? 设置输出开关  */
			conn.setDoInput(true); 				/*-? 设置输入开关 */
			conn.setUseCaches(false); 			/*-? 设置是否缓存 */
			conn.setRequestProperty("Content-Type",
					"application/json;charset=" + ENCODE_CODE); /*-? 设置请求Content-Type 属性参数 编码格式 POST需要用到 */
			conn.setRequestProperty("Content-Length",
					String.valueOf(data.length)); /*-? 设置请求Content-Length 参数字符长度 POST需要用到 */
			String base64Encodeup = org.apache.commons.codec.binary.StringUtils.newStringUtf8(Base64.encodeBase64((userName+":"+passWord).getBytes()));
			conn.setRequestProperty ("Authorization", "Basic "+base64Encodeup);
			// conn.connect(); /* Get方式需要用到 */

			/** - 获取输出流对象 执行输出 POST方式 需要的代码块 */
			os = conn.getOutputStream();
			os.write(data);

			/** - 成功请求 200反馈 需要接收返回值 */
			if (conn.getResponseCode() == 200) {
				/* 拿到输入流对象 */
				in = conn.getInputStream();
				getResponseData(in,respStr);
				in.close();
				LOG.info("The httpRequest server response result : {} ", respStr);
			} else {  // 非200 处理
				/* 拿到输入流对象 */
				in = conn.getErrorStream();
				getResponseData(in,respStr);
				in.close();
				respStatus = "R";
				LOG.error("The httpRequest server response result : {} ", respStr);
			}

			os.close();
			conn.disconnect();

		} catch (UnsupportedEncodingException e) {
			LOG.error("Send info to URL client error : {} ", e.getMessage());
			respStr.append(e.getMessage());
			respStatus = "R";
		} catch (MalformedURLException e) {
			LOG.error("Send info to URL client error : {} ", e.getMessage());
			respStr.append(e.getMessage());
			respStatus = "R";
		} catch (ProtocolException e) {
			LOG.error("Send info to URL client error : {} ", e.getMessage());
			respStr.append(e.getMessage());
			respStatus = "R";
		} catch (IOException e) {
			LOG.error("Send info to URL client error : {} ", e.getMessage());
			respStr.append(e.getMessage());
			respStatus = "R";
		} finally {

			try {
				if (bReader != null) {
					bReader.close();
				}
				if (in != null) {
					in.close();
				}
				if (os != null) {
					os.close();
				}
				if (conn != null) {
					conn.disconnect();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}

		}

		respMap.put("status", respStatus);
		respMap.put("msg", respStr);

		return respStr.toString();

	}

	private static void getResponseData(InputStream input,StringBuffer respStr) throws IOException {
		
		BufferedReader bReader = new BufferedReader(new InputStreamReader(input, ENCODE_CODE));
		String str = null;

		while ((str = bReader.readLine()) != null) {
			respStr.append(str);
		}

		bReader.close();
	}

	/**
	 * 使用Get方式 -- 需要传递 http请求的URL地址 -- 可传递Proxy代理服务 （不需要代理传递NULL） -- 可传递代理服务器的端口
	 * （不需要代理传递NULL）
	 * 
	 * Get请求方式 传递Url自已带上参数 带参数之前如果有中文包含 将其转化后传递 -- String url =
	 * "http://xxxx/a.do?id=123&content=" + StrUtil.encodeURL(xxx) + ";
	 * HttpUtil.doGetRequest(url,xx,xx)
	 * 
	 * @param requestUrlParam
	 *            请求URL
	 * @param proxy
	 *            代理服务
	 * @param port
	 *            代理服务端口
	 * @return Map<String,Object> key:status value: S or R key:data
	 * @version 1.0
	 * @since 2015-12-11
	 */
	public static Map<String, Object> doGetRequest(String requestUrlParam, String proxy, Integer port) {

		StringBuffer params = new StringBuffer();
		StringBuffer respStr = new StringBuffer();
		Map<String, Object> respMap = new HashMap<String, Object>();
		String respStatus = "S";

		InputStream in = null;
		BufferedReader bReader = null;
		OutputStream os = null;
		HttpURLConnection conn = null;

		try {

			/** - 实例化URL对象 */
			URL url = new URL(requestUrlParam);

			/** - 打开 HttpURLConnection 链接 */
			conn = openConn(url, proxy, port);

			conn.setConnectTimeout(5 * 1000); /*-? 设置请求超时时间 */
			conn.setRequestMethod("GET"); /*-? 设置请求方式 */
			conn.setDoOutput(true); /*-? 设置输出开关 */
			conn.setDoInput(true); /*-? 设置输入开关 */
			conn.setUseCaches(false); /*-? 设置是否缓存 */

			conn.connect(); /*-? 执行HTTP请求操作   GET需要用到 */

			/** - 获取输出流对象 执行输出 POST方式 需要的代码块 */
			os = conn.getOutputStream();
			os.write(params.toString().getBytes());

			/** - 成功请求 200反馈 需要接收返回值 */
			if (conn.getResponseCode() == 200) {

				/* 拿到输入流对象 */
				in = conn.getInputStream();
				/* 实例化BufferedReader对象 */
				bReader = new BufferedReader(new InputStreamReader(in, ENCODE_CODE));
				String str = null;

				while ((str = bReader.readLine()) != null) {
					respStr.append(str);
				}

				bReader.close();
				in.close();

				LOG.error("The httpRequest server response result : {} ", respStr);

			}

			os.close();
			conn.disconnect();

		} catch (UnsupportedEncodingException e) {
			LOG.error("Send info to URL client error : {} ", e.getMessage());
			respStr.append(e.getMessage());
			respStatus = "R";
			e.printStackTrace();
		} catch (MalformedURLException e) {
			LOG.error("Send info to URL client error : {} ", e.getMessage());
			respStr.append(e.getMessage());
			respStatus = "R";
			e.printStackTrace();
		} catch (ProtocolException e) {
			LOG.error("Send info to URL client error : {} ", e.getMessage());
			respStr.append(e.getMessage());
			respStatus = "R";
			e.printStackTrace();
		} catch (IOException e) {
			LOG.error("Send info to URL client error : {} ", e.getMessage());
			respStr.append(e.getMessage());
			respStatus = "R";
			e.printStackTrace();
		} finally {

			try {
				if (bReader != null) {
					bReader.close();
				}
				if (in != null) {
					in.close();
				}
				if (os != null) {
					os.close();
				}
				if (conn != null) {
					conn.disconnect();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}

		}

		respMap.put("status", respStatus);
		respMap.put("data", respStr);

		return respMap;

	}

	/**
	 * 根据URL对象 获取HttpURLConnection对象 --是否需要利用代理机制（不需要可以传递空值）
	 * 
	 * @param url
	 * @param proxy
	 * @return Boolean
	 * @version 1.0
	 * @throws IOException
	 * @since 2015-12-11
	 */
	private static HttpURLConnection openConn(URL url, String proxyName, Integer port) throws IOException {

		if (proxyName != null) {
			Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyName, port));
			return (HttpURLConnection) url.openConnection(proxy);
		}

		return (HttpURLConnection) url.openConnection();

	}

}
